package network

import (
	"context"
	//	"encoding/json"

	. "gitee.com/liukexing/isrn/api"
)

/*
USAGE
  ipfs swarm - Interact with the swarm.

SYNOPSIS
  ipfs swarm

DESCRIPTION

  'ipfs swarm' is a tool to manipulate the network swarm. The swarm is the
  component that opens, listens for, and maintains connections to other
  ipfs peers in the internet.

SUBCOMMANDS
  ipfs swarm addrs                   - List known addresses. Useful for debugging.
  ipfs swarm connect <address>...    - Open connection to a given address.
  ipfs swarm disconnect <address>... - Close connection to a given address.
  ipfs swarm filters                 - Manipulate address filters.
  ipfs swarm peers                   - List peers with open connections.

  Use 'ipfs swarm <subcmd> --help' for more information about each command.
*/

type SwarmCommand struct {
	Shell
}

/*
USAGE
  ipfs swarm addrs - List known addresses. Useful for debugging.

SYNOPSIS
  ipfs swarm addrs

DESCRIPTION

  'ipfs swarm addrs' lists all addresses this node is aware of.

SUBCOMMANDS
  ipfs swarm addrs listen - List interface listening addresses.
  ipfs swarm addrs local  - List local addresses.

  Use 'ipfs swarm addrs <subcmd> --help' for more information about each command.
*/

type SwarmAddrs struct {
	Addrs map[string][]string
}

func (s *SwarmCommand) Addrs() (*SwarmAddrs, error) {
	cmdargs := []string{}

	out := &SwarmAddrs{}
	err := s.Request("swarm/addrs", cmdargs...).Exec(context.Background(), out)
	if err != nil {
		return nil, err
	}
	return out, nil

	//	req := s.NewRequest(context.Background(), "swarm/addrs", cmdargs...)

	//	resp, err := req.Send(s.HttpCli)
	//	if err != nil {
	//		return nil, err
	//	}
	//	defer resp.Close()

	//	if resp.Error != nil {
	//		return nil, resp.Error
	//	}

	//	out := &SwarmAddrs{}
	//	err = json.NewDecoder(resp.Output).Decode(out)
	//	if err != nil {
	//		return nil, err
	//	}

	//	return out, nil
}

/*
USAGE
  ipfs swarm connect <address>... - Open connection to a given address.

SYNOPSIS
  ipfs swarm connect [--] <address>...

ARGUMENTS

  <address>... - Address of peer to connect to.

DESCRIPTION

  'ipfs swarm connect' opens a new direct connection to a peer address.

  The address format is an IPFS multiaddr:

  ipfs swarm connect /ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ
*/

type SwarmObjects struct {
	Strings []string
}

func (s *SwarmCommand) Connect(address string) (*SwarmObjects, error) {
	cmdargs := []string{address}
	out := &SwarmObjects{}
	err := s.Request("swarm/connect", cmdargs...).Exec(context.Background(), out)
	if err != nil {
		return nil, err
	}
	return out, nil
	//	req := s.NewRequest(context.Background(), "swarm/connect", cmdargs...)

	//	resp, err := req.Send(s.HttpCli)
	//	if err != nil {
	//		return nil, err
	//	}
	//	defer resp.Close()

	//	if resp.Error != nil {
	//		return nil, resp.Error
	//	}

	//	out := &SwarmObjects{}
	//	err = json.NewDecoder(resp.Output).Decode(out)
	//	if err != nil {
	//		return nil, err
	//	}

	//	return out, nil
}

/*
USAGE
  ipfs swarm disconnect <address>... - Close connection to a given address.

SYNOPSIS
  ipfs swarm disconnect [--] <address>...

ARGUMENTS

  <address>... - Address of peer to disconnect from.

DESCRIPTION

  'ipfs swarm disconnect' closes a connection to a peer address. The address
  format is an IPFS multiaddr:

  ipfs swarm disconnect /ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ

  The disconnect is not permanent; if ipfs needs to talk to that address later,
  it will reconnect.
*/
func (s *SwarmCommand) Disconnect(address string) (*SwarmObjects, error) {
	cmdargs := []string{address}
	out := &SwarmObjects{}
	err := s.Request("swarm/connect", cmdargs...).Exec(context.Background(), out)
	if err != nil {
		return nil, err
	}
	return out, nil
	//	req := s.NewRequest(context.Background(), "swarm/disconnect", cmdargs...)

	//	resp, err := req.Send(s.HttpCli)
	//	if err != nil {
	//		return nil, err
	//	}
	//	defer resp.Close()

	//	if resp.Error != nil {
	//		return nil, resp.Error
	//	}

	//	out := &SwarmObjects{}
	//	err = json.NewDecoder(resp.Output).Decode(out)
	//	if err != nil {
	//		return nil, err
	//	}

	//	return out, nil
}

/*
USAGE
  ipfs swarm filters - Manipulate address filters.

SYNOPSIS
  ipfs swarm filters

DESCRIPTION

  'ipfs swarm filters' will list out currently applied filters. Its subcommands
  can be used to add or remove said filters. Filters are specified using the
  multiaddr-filter format:

  Example:

      /ip4/192.168.0.0/ipcidr/16

  Where the above is equivalent to the standard CIDR:

      192.168.0.0/16

  Filters default to those specified under the "Swarm.AddrFilters" config key.

SUBCOMMANDS
  ipfs swarm filters add <address>... - Add an address filter.
  ipfs swarm filters rm <address>...  - Remove an address filter.

  Use 'ipfs swarm filters <subcmd> --help' for more information about each command.
*/

func (s *SwarmCommand) Filters() (*SwarmObjects, error) {
	cmdargs := []string{}
	out := &SwarmObjects{}
	err := s.Request("swarm/filters", cmdargs...).Exec(context.Background(), out)
	if err != nil {
		return nil, err
	}
	return out, nil
	//	req := s.NewRequest(context.Background(), "swarm/filters", cmdargs...)

	//	resp, err := req.Send(s.HttpCli)
	//	if err != nil {
	//		return nil, err
	//	}
	//	defer resp.Close()

	//	if resp.Error != nil {
	//		return nil, resp.Error
	//	}

	//	out := &SwarmObjects{}
	//	err = json.NewDecoder(resp.Output).Decode(out)
	//	if err != nil {
	//		return nil, err
	//	}

	//	return out, nil
}

func (s *SwarmCommand) FiltersAdd(address string) (*SwarmObjects, error) {
	cmdargs := []string{address}
	out := &SwarmObjects{}
	err := s.Request("swarm/filters/add", cmdargs...).Exec(context.Background(), out)
	if err != nil {
		return nil, err
	}
	return out, nil
	//	req := s.NewRequest(context.Background(), "swarm/filters/add", cmdargs...)

	//	resp, err := req.Send(s.HttpCli)
	//	if err != nil {
	//		return nil, err
	//	}
	//	defer resp.Close()

	//	if resp.Error != nil {
	//		return nil, resp.Error
	//	}

	//	out := &SwarmObjects{}
	//	err = json.NewDecoder(resp.Output).Decode(out)
	//	if err != nil {
	//		return nil, err
	//	}

	//	return out, nil
}

func (s *SwarmCommand) FiltersRm(address string) (*SwarmObjects, error) {
	cmdargs := []string{address}
	out := &SwarmObjects{}
	err := s.Request("swarm/filters/rm", cmdargs...).Exec(context.Background(), out)
	if err != nil {
		return nil, err
	}
	return out, nil
	//	req := s.NewRequest(context.Background(), "swarm/filters/rm", cmdargs...)

	//	resp, err := req.Send(s.HttpCli)
	//	if err != nil {
	//		return nil, err
	//	}
	//	defer resp.Close()

	//	if resp.Error != nil {
	//		return nil, resp.Error
	//	}

	//	out := &SwarmObjects{}
	//	err = json.NewDecoder(resp.Output).Decode(out)
	//	if err != nil {
	//		return nil, err
	//	}

	//	return out, nil
}

/*
USAGE
  ipfs swarm peers - List peers with open connections.

SYNOPSIS
  ipfs swarm peers [--verbose | -v] [--streams] [--latency]

OPTIONS

  -v,      --verbose bool - display all extra information.
  --streams          bool - Also list information about open streams for each peer.
  --latency          bool - Also list information about latency to each peer.

DESCRIPTION

  'ipfs swarm peers' lists the set of peers this node is connected to.
*/

type SwarmPeers struct {
	Peers []struct {
		Addr    string
		Peer    string
		Latency string
		Muxer   string
		Streams []struct {
			Protocol string
		}
	}
}

func (s *SwarmCommand) Peers(streams, latency bool) (*SwarmPeers, error) {
	cmdargs := []string{}
	out := &SwarmPeers{}
	err := s.Request("swarm/peers", cmdargs...).Exec(context.Background(), out)
	if err != nil {
		return nil, err
	}
	return out, nil
	//	req := s.NewRequest(context.Background(), "swarm/peers", cmdargs...)

	//	if streams {
	//		req.Opts["streams"] = "true"
	//	}

	//	if latency {
	//		req.Opts["latency"] = "true"
	//	}

	//	resp, err := req.Send(s.HttpCli)
	//	if err != nil {
	//		return nil, err
	//	}
	//	defer resp.Close()

	//	if resp.Error != nil {
	//		return nil, resp.Error
	//	}

	//	out := &SwarmPeers{}
	//	err = json.NewDecoder(resp.Output).Decode(out)
	//	if err != nil {
	//		return nil, err
	//	}

	//	return out, nil
}
